#include<iostream>
#include<pthread.h>
#include<iostream>
#include <unistd.h>


#define TNUM 4
typedef void(*func_t)(const std::string &name, pthread_mutex_t *pmtx, pthread_cond_t *pcond);
volatile bool quit = false;
// //静态初始化方法，不需要destroy
// pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
// pthread_cond_t cond = PTHREAD_COND_INITIALIZER;



class ThreadData
{
public:
    ThreadData(const std::string &name, func_t func,pthread_mutex_t *pmtx, pthread_cond_t *pcond)
    :_name(name),_func(func),_pmtx(pmtx), _pcond(pcond)
    {}

public:

    std::string _name;
    func_t _func;
    pthread_mutex_t *_pmtx;
    pthread_cond_t *_pcond;
};


void func1(const std::string &name, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while(!quit)
    {
        //记住wait一定要在加锁和解锁之间
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcond, pmtx);   //默认该线程在执行好的时候，wait代码被执行，当前线程会被立即阻塞

        std::cout<<name<<"running ...."<<std::endl;
        sleep(1);

        pthread_mutex_unlock(pmtx);
    }
}
void func2(const std::string &name, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while(!quit)
    {
        //记住wait一定要在加锁和解锁之间
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcond, pmtx);   //默认该线程在执行好的时候，wait代码被执行，当前线程会被立即阻塞
        std::cout<<name<<"running ...."<<std::endl;
        sleep(1);

        pthread_mutex_unlock(pmtx);
    }
}
void func3(const std::string &name, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while(!quit)
    {

        //记住wait一定要在加锁和解锁之间
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcond, pmtx);   //默认该线程在执行好的时候，wait代码被执行，当前线程会被立即阻塞
        std::cout<<name<<"running ...."<<std::endl;
        sleep(1);
        pthread_mutex_unlock(pmtx);
    }   
}
void func4(const std::string &name, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while(!quit)
    {

        //记住wait一定要在加锁和解锁之间
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcond, pmtx);   //默认该线程在执行好的时候，wait代码被执行，当前线程会被立即阻塞
        std::cout<<name<<"running ...."<<std::endl;
        sleep(1);
        pthread_mutex_unlock(pmtx);
    }    
}

void *Entry(void* args)
{   
    ThreadData* td = (ThreadData*)args;    // td 在每个线程自己私有的栈空间中保存
    td->_func(td->_name, td->_pmtx, td->_pcond);   //他是一个函数，调用完成就返回
    delete td;
    return nullptr;
}

int main()
{
    pthread_t tids[TNUM];
    func_t func[TNUM] = {func1, func2, func3, func4};  //定义一个函数指针数组

    pthread_mutex_t mtx;
    pthread_cond_t cond;
    pthread_mutex_init(&mtx, nullptr);   //动态初始化，得销毁
    pthread_cond_init(&cond, nullptr);


    for(int i = 0;i<TNUM;i++)
    {
        std::string name = "Thread ";
        name+=std::to_string(i+1);
        ThreadData *td = new ThreadData(name, func[i], &mtx, &cond);
        pthread_create(tids+i, nullptr, Entry, (void*)td);   //创建线程
    }

    sleep(5);

    //控制新线程
    int cnt = 10;
    while(cnt)
    {
        std::cout<<" making thread run code...."<<std::endl;
        pthread_cond_signal(&cond);   //唤醒其中一个线程
        sleep(1);
        cnt--;
    }

    std::cout<<"控制结束"<<std::endl;
    quit = true;

    pthread_cond_broadcast(&cond);
    //线程等待
    for(int i = 0;i<TNUM;i++)
    {
        pthread_join(tids[i], nullptr);
        std::cout<<" thread: "<<tids[i]<<" quit "<<std::endl;
    }




    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&cond);



    return 0;
}